{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 调用函数\n",
    "要调用一个函数，需要知道函数的**名称**和**参数**。  \n",
    "比如求绝对值的函数`abs`,只有一个参数。  \n",
    "可以通过交互式命令'help(abs)'来查看函数的帮助信息。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Help on built-in function abs in module builtins:\n",
      "\n",
      "abs(x, /)\n",
      "    Return the absolute value of the argument.\n",
      "\n"
     ]
    }
   ],
   "source": [
    "help(abs)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "500"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 调用abs函数：\n",
    "abs(-500)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "调用函数时，如果传入参数的数量不对，会报TypeError错误，并且Python会明确告知：  \n",
    "abs()有且仅有1个参数，但给出了两个。如下所示："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "ename": "TypeError",
     "evalue": "abs() takes exactly one argument (2 given)",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mTypeError\u001b[0m                                 Traceback (most recent call last)",
      "\u001b[1;32m<ipython-input-2-e65aea954a39>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m()\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[0mabs\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;36m1\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;36m5\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[1;31mTypeError\u001b[0m: abs() takes exactly one argument (2 given)"
     ]
    }
   ],
   "source": [
    "abs(1, 5)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "如果传入的**参数数量**是对的，但**参数类型**不能被函数所接受，也会报TypeError错误，并且给出错误信息。如下所示：  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "ename": "TypeError",
     "evalue": "bad operand type for abs(): 'str'",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mTypeError\u001b[0m                                 Traceback (most recent call last)",
      "\u001b[1;32m<ipython-input-4-4219faed7d90>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m()\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[0mabs\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m'abc'\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[1;31mTypeError\u001b[0m: bad operand type for abs(): 'str'"
     ]
    }
   ],
   "source": [
    "abs('abc')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 创建函数\n",
    "在Python中，使用`def`语句创建函数。  \n",
    "我们以自定义一个求绝对值的函数\"my_abs\"为例："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "def my_abs(x):\n",
    "    if x >= 0:\n",
    "        return x\n",
    "    else:\n",
    "        return -x"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "500"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 测试并调用my_abs函数。\n",
    "my_abs(-500)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "函数体内部的语句在执行时，一旦执行到return时，函数就执行完毕，并将结果返回。   \n",
    "因此，函数内部通过条件判断和循环可以实现非常复杂的逻辑。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 函数的参数"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "定义函数的时候，我们把参数的**名称**和**位置**确定下来，函数的接口就定义完成了。  \n",
    "对于函数的调用者来说，只需要知道如何传递正确的参数，以及函数将返回什么样的值就够了。  \n",
    "函数内部的复杂逻辑被封装起来，调用者无需了解。  \n",
    "\n",
    "函数的定义很简单，但灵活的非常大。  \n",
    "除了正常定义的必选参数外，还可以使用默认参数、可变参数和关键字参数；  \n",
    "使得函数定义出来的接口，不但能处理复杂的参数，还可以简化调用者的代码。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 默认参数"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "举例说明，先写一个计算$ x^{2} $ 的函数："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "def power(x):\n",
    "    return x * x"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "当我们调用`power`函数时，必须传入有且仅有的一个参数`x`:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "81"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "power(9)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "现在，如果我们想计算$x^{3}$该怎么办？  \n",
    "可以再定义一个power3函数，但是如果要计算$x^{4}$、$x^{5}$......呢？  \n",
    "我们不可能定义无限多个函数。  \n",
    "\n",
    "你也许想到了，可以把power(x)修改为power(x, n),用来计算$x^{n}$，说干就干："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "def power(x, n):\n",
    "    s = 1\n",
    "    while n > 0: # 控制乘方的次数\n",
    "        n = n - 1\n",
    "        s = s * x # x是底数\n",
    "    return s"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "243"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "power(3, 5)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "但是，调用旧的代码失败了，原因是我们增加了一个参数，导致旧的代码无法被正常调用，如下所示："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "ename": "TypeError",
     "evalue": "power() missing 1 required positional argument: 'n'",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mTypeError\u001b[0m                                 Traceback (most recent call last)",
      "\u001b[1;32m<ipython-input-5-3438fa90600b>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m()\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[0mpower\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;36m9\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[1;31mTypeError\u001b[0m: power() missing 1 required positional argument: 'n'"
     ]
    }
   ],
   "source": [
    "power(9)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "这个时候，**默认参数**就派上用场了。由于我们经常计算$x^{2}$，所以，完全可以把第二个参数n的默认值设定为2："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "def power(x, n=2):\n",
    "    s = 1\n",
    "    while n > 0: #控制乘方的次数\n",
    "        n = n - 1\n",
    "        s = s * x # x是底数\n",
    "    return s"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "这样，当我们调用power(5)时，相当于调用power(5, 2)："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "25"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "power(5)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "对于`n>2`的其他情况，就必须明确地传入`n`，比如`power(5, 3)`。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.3429999999999999"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "power(0.7, 3)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "从上面的例子可以看出，默认参数可以简化函数的调用。设置默认参数时，有几个注意点：  \n",
    "- 必选参数在前，默认参数在后，否则Python的解释器会报错；\n",
    "- 如何设置默认参数：当函数有多个参数时，把变化大的参数放在前面，变化小的参数放在后面。  \n",
    "\n",
    "使用默认参数最大的好处是能降低调用函数的难度。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 可变参数\n",
    "顾名思义，可变参数就是指传入的参数个数是可变的。  \n",
    "\n",
    "我们以数学题为例，给定一组数字a,b,c……，计算$a^2 + b^2 + c^2 + ……$。  \n",
    "\n",
    "要定义出这个函数，我们必须确定输入的参数。由于参数个数不确定，我们首先想到可以把a, b, c……作为一个list或tuple传进来。这样，函数的定义如下："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [],
   "source": [
    "def calc(numbers):\n",
    "    sum = 0\n",
    "    for n in numbers:\n",
    "        sum = sum + n * n\n",
    "    return sum"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "14"
      ]
     },
     "execution_count": 26,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "calc([1, 2, 3])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "35"
      ]
     },
     "execution_count": 28,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "calc((1, 3, 5))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "如果利用可变参数，则需要把函数的参数改为可变参数形式："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "def calc(*numbers):\n",
    "    sum = 0\n",
    "    for n in numbers:\n",
    "        sum = sum + n * n\n",
    "    return sum"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "调用函数的方式可以简化成这样："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "14"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "calc(1, 2, 3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "55"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "calc(1, 2, 3, 4, 5)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "定义可变参数和定义list或tuple参数相比，仅仅在参数前面加了一个`*`。  \n",
    "在函数内部，参数numbers接收到的是一个tuple，因此函数代码完全不变。  \n",
    "可是，在调用该函数时，却可以传入任意个参数，包括0个参数："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "calc()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "如果已有一个list或tuple，要调用一个可变参数该怎么办？  \n",
    "Python允许你在list或tuple前面加一个`*`，把list或tuple的元素变成可变参数传进去："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "55"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "nums = [1, 2, 3, 4, 5]\n",
    "calc(*nums)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "这种写法相当有用，而且很常见。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 关键字参数"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "可变参数允许你传入0个或任意个参数，这些可变参数在函数调用时自动组装成一个tuple。  \n",
    "而关键字参数允许你传入0个或任意个含参数名的参数，这些关键字参数在函数内部自动组装成一个dict。  \n",
    "请看示例："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [],
   "source": [
    "def person(name, age, **kw):\n",
    "    print(\"name:\", name, \"age:\", age, \"other:\", kw)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "函数person除了必选参数`name`和`age`外，还接受关键字参数`kw`。  \n",
    "在调用该函数时，可以只传入必选参数："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "name: Michael age: 30 other: {}\n"
     ]
    }
   ],
   "source": [
    "person(\"Michael\", 30)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "也可以传入任意个数的关键字参数："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "name: Henry age: 30 other: {'gender': '男', 'job': 'Engineer'}\n"
     ]
    }
   ],
   "source": [
    "person(\"Henry\", 30, gender=\"男\", job=\"Engineer\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "关键字参数有什么用呢？  \n",
    "它可以扩展函数的功能。比如，在person函数里，我们保证能接收到name和age这两个参数。但是，如果调用者原意提供更多的参数，我们也能收到。 \n",
    "\n",
    "试想你正在做一个用户注册的功能，除了用户名和年龄是必填项外，其他的都是选填项，利用关键字参数来定义这个函数，就能满足该注册需求。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 混合参数\n",
    "在Python中定义函数，可以用必选参数、默认参数、可变参数和关键字参数，这4种参数都可以一起使用，或者只用其中某些。  \n",
    "但是请注意，参数定义的顺序是：必选参试、默认参数、可变参数和关键字参数。  \n",
    "\n",
    "比如定义一个函数，包含上述4种参数："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [],
   "source": [
    "def func(a, b, c=0, *args, **kw):\n",
    "    print('a =',a,'b =', b, 'c =', c, 'args =', args, 'kw =', kw)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "在调用函数的时候，Python解释器自动按照参数位置和参数名把对应的参数传进去。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "a = 1 b = 2 c = 3 args = ('a', 'b') kw = {'x': 99, 'y': 100}\n"
     ]
    }
   ],
   "source": [
    "func(1, 2, 3, 'a', 'b', x=99, y=100)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 递归\n",
    "1、递归就是在过程或函数里调用自身；  \n",
    "2、在使用递归策略时，必须有一个明确的“递归结束条件”，称为**递归出口**。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "递归算法一般用于解决3类问题：  \n",
    "1、数据的定义是按递归定义的（比如Fibnacci函数）；  \n",
    "2、问题解法按递归算法实现（回溯）；    \n",
    "3、数据的结构形式是按递归定义的（比如树的遍历，图的搜索）。  \n",
    "\n",
    "**递归的缺点：**  \n",
    "递归算法解题的运行效率较低。在递归调用的过程中，系统为每一层的返回点、局部量等开辟了栈来存储。递归次数过多容易造成栈溢出等。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**示例：斐波那契数列**  \n",
    "斐波那契数列在十三世纪由意大利数学家斐波那契发现。  \n",
    "数列中的一系列数字常被人们称之为神奇数、奇异数。  \n",
    "具体数列为：0，1，1，2，3，5，8，13，21，34，55，89，144，233……，从该数列的第三项数字开始，每个数字等于前两个相邻数字之和。  \n",
    "而斐波那契数列中相邻两数之商就接近黄金分割数0.618，与这一数字相关的0.191、0.382、0.5和0.809等数字就构成了股市中关于市场时间和空间计算的重要数字。  "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "在金融市场的分析方法中，斐波那契数字频繁出现。  \n",
    "例如，在波浪理论中，一轮牛市行情可以用1个上升浪来表示，也可以用5个低一个层次的小浪来表示，还可以继续细分为21个或89个小浪；  \n",
    "在空间分析体系中，反弹行情的高度通常是前方下降趋势幅度的0.382、0.5、0.618；  \n",
    "回调行情通常是前方上升趋势的0.382、0.5和0.618。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377]\n"
     ]
    }
   ],
   "source": [
    "def fib1(num):\n",
    "    result=[0, 1]\n",
    "    # 循环num-2次\n",
    "    for i in range(num-2):\n",
    "        result.append(result[-2]+result[-1])\n",
    "    return result\n",
    "print (fib1(15)) # 打印出斐波那契数列的前15项"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "6765\n",
      "read: 0.001789 s\n"
     ]
    }
   ],
   "source": [
    "import time\n",
    "\n",
    "start = time.clock()\n",
    "def fib2(n):\n",
    "    if n<=2:\n",
    "        return 1\n",
    "    else:\n",
    "        return fib(n-1)+fib(n-2)\n",
    "print(fib2(20))\n",
    "end = time.clock()\n",
    "\n",
    "print(\"read: %f s\"%(end - start))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "6765\n",
      "read: 0.003269 s\n"
     ]
    }
   ],
   "source": [
    "start = time.clock()\n",
    "def fib3(n):\n",
    "    return 1 and n<=2 or fib(n-1)+fib(n-2)\n",
    "print(fib3(20))\n",
    "end = time.clock()\n",
    "\n",
    "print(\"read: %f s\" %(end-start))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 匿名函数\n",
    "Python使用lambda关键字来创建匿名函数。\n",
    "- lambda只是一个表达式，函数体比def简单很多。\n",
    "- lambda的主体是一个表达式，而不是一个代码块。仅仅能在lambda表达式中封装有限的逻辑进去。\n",
    "- lambda函数拥有自己的名字空间，而不能访问自有参数列表之外或全局名字空间里的参数。\n",
    "- 虽然lambda函数看起来只能写一行，却不等同于C或C++的内联函数，后者的目的是调用小函数时不占用栈内存从而增加运行效率。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "55\n",
      "read: 0.000574\n"
     ]
    }
   ],
   "source": [
    "import time\n",
    "\n",
    "start = time.clock()\n",
    "fib = lambda n,x=0,y=1:x if not n else fib(n-1, y, x+y)\n",
    "print (fib(10))\n",
    "end = time.clock()\n",
    "\n",
    "print(\"read: %f\" %(end-start))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "6765\n",
      "read: 0.004137 秒\n"
     ]
    }
   ],
   "source": [
    "start = time.clock()\n",
    "fib = lambda n:1 if n<=2 else fib(n-1)+fib(n-2)\n",
    "print (fib(20))\n",
    "end = time.clock()\n",
    "\n",
    "print(\"read: %f 秒\" %(end-start))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Python中的多态\n",
    "一个操作的意义取决于被操作对象的类型"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [],
   "source": [
    "def times(x, y):\n",
    "    return x*y"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "8"
      ]
     },
     "execution_count": 28,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "times(2,4)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'Python Python Python Python '"
      ]
     },
     "execution_count": 29,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 传递了与上不同的数据类型\n",
    "times('Python ', 4)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 打印出s1和s2的交集\n",
    "def intersect(s1, s2):\n",
    "    return [x for x in s1 if x in s2]\n",
    "s1 = 'Python'\n",
    "s2 = 'python'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['y', 't', 'h', 'o', 'n']"
      ]
     },
     "execution_count": 31,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "intersect(s1, s2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[1, 2]"
      ]
     },
     "execution_count": 32,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 传递与上不同的数据类型\n",
    "intersect([1,2,3,5],[1,2,4])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.5"
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {},
   "number_sections": true,
   "sideBar": true,
   "skip_h1_title": false,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {},
   "toc_section_display": true,
   "toc_window_display": true
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
